home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / inter54e.zip / INTSUM16.ZIP / INTSUM.CPP < prev    next >
C/C++ Source or Header  |  1996-10-13  |  19KB  |  599 lines

  1. //********************************************************************
  2. //  INTSUM.CPP - Display/search program for Ralf Brown's              
  3. //               Interrupt List.                                      
  4. //                                                                    
  5. //  Copyright (c) 1996 Daniel D. Miller                               
  6. //                                                                    
  7. //  Last Update:  09-08-95 08:42pm                                    
  8. //                                                                    
  9. //  Compile with makefile                                             
  10. //                                                                    
  11. //********************************************************************
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <dos.h>
  17. #include <graph.h>
  18. #include "intsum.hpp"
  19. #include "err_exit.hpp"
  20. #include "keycodes.h"
  21. // #include <memcheck.h>
  22.  
  23. //*****************************************************************
  24. main(int argc, char** argv)
  25.    {
  26.    int done, count ;
  27.    unsigned j ;
  28.    uchar char_attr ;
  29.  
  30.    //  make sure at least DOS 3.0 is running
  31.    if (_osmajor < 3)
  32.       error_exit(OLD_DOS_VERSION, NULL) ;
  33.  
  34.    //  get path for executable file
  35.    _splitpath(argv[0], inidrive, inipath, NULL, NULL) ;
  36.  
  37.    //  calculate video parameters
  38.    char_attr = get_char_attr() ;
  39.    get_vsize() ;
  40.    window_rows = screen_rows - DATA_TOP ; //  base-1
  41.    select_video_seg(0) ;   // auto-detect video segment
  42.  
  43.    //  initialize the path for IntList files, 
  44.    //  before reading INI file.
  45.    strcpy(ildrive, inidrive) ;
  46.    strcpy(ilpath , inipath) ;
  47.  
  48.    //  search for/parse INI file
  49.    read_ini_file() ;
  50.  
  51.    //  allocate raw-data read buffer
  52.    readptr = new char[(unsigned) BFR_SIZE] ;
  53.    if (readptr == NULL) 
  54.       error_exit(OUT_OF_MEMORY, NULL) ;
  55.  
  56.    //  allocate ref-file buffers
  57.    ref.bfr[0] = new sum_conv[isl_lines] ;
  58.    if (ref.bfr[0] == NULL) 
  59.       error_exit(OUT_OF_MEMORY, NULL) ;
  60.    ref.bfr[1] = new sum_conv[isl_lines] ;
  61.    if (ref.bfr[1] == NULL) 
  62.       error_exit(OUT_OF_MEMORY, NULL) ;
  63.  
  64.    //  allocate ref-search buffer
  65.    search.bfr = new sum_conv[isl_lines] ;
  66.    if (search.bfr == NULL) 
  67.       error_exit(OUT_OF_MEMORY, NULL) ;
  68.  
  69.    //  allocate list-file buffers
  70.    list.bfr[0] = new lines[list_lines] ;
  71.    if (list.bfr[0] == NULL) 
  72.       error_exit(OUT_OF_MEMORY, NULL) ;
  73.    list.bfr[1] = new lines[list_lines] ;
  74.    if (list.bfr[1] == NULL) 
  75.       error_exit(OUT_OF_MEMORY, NULL) ;
  76.  
  77.    //  search for interrup.idx
  78.    //  Build it if not present
  79.    //  
  80.    //  NOTE: if files are opened in TEXT mode,
  81.    //        EOLs get translated from CRLF in file to \n in buffer,
  82.    //        and "bytes read" is not what was asked for.
  83.    //        This program uses BINARY to solve some of these problems.
  84.    _makepath(tempstr, ildrive, ilpath, "interrup", "idx") ;
  85.    index = fopen(tempstr, "rb") ;
  86.    if (index == NULL) 
  87.       {
  88.       build_index() ;
  89.       _makepath(tempstr, ildrive, ilpath, "interrup", "idx") ;
  90.       index = fopen(tempstr, "rb") ;
  91.       if (index == NULL) 
  92.          error_exit(NO_READ_FILE, "interrup.idx") ;
  93.       }
  94.    //  leave ref file open
  95.  
  96.    //  initialize variables and read first ref buffer
  97.    ref.cur_bfr  = 0 ;
  98.    ref.offset   = 0 ;
  99.    fpos_t pos = 0 ;
  100.    fill_ref_buffers(pos) ;
  101.    
  102.    //****************************************
  103.    //  hold off building display until 
  104.    //  setup operations are successful.
  105.    //****************************************
  106.  
  107.    //  hide the cursor
  108.    hide_cursor() ;
  109.  
  110.    //  display our logo
  111.    clear_display(MAIN_TEXT) ;
  112.    display_logo() ;
  113.  
  114.    // display the first window
  115.    display_ref_file() ;
  116.  
  117.    //  main keyboard handler
  118.    char srchstr[81] ;
  119.    srchstr[0] = 0 ;  // reset initial search string
  120.    unsigned rtemp ;
  121.    done = 0 ;
  122.    while (!done) 
  123.       {
  124.       mark_cursor_line(ivideo.currow, SELECTED) ;
  125.       unsigned indata = get_key() ;
  126.       mark_cursor_line(ivideo.currow, MAIN_TEXT) ;
  127.       switch (indata) 
  128.          {
  129.          case Key_ENTER:   //  seek info on current entry
  130.             rtemp = ivideo.currow ;
  131.             process_list_file(0, NULL) ;
  132.             ivideo.currow = rtemp ;
  133.             display_ref_file() ;
  134.             break;
  135.  
  136.          case Key_UP:
  137.             scroll_page_down() ;
  138.             break;
  139.  
  140.          case Key_HOME:
  141.             //  position cursor at beginning of file
  142.             pos = 0 ;
  143.             fill_ref_buffers(pos) ;
  144.             ref.offset = 0 ;
  145.             ref.cur_bfr = 0 ;
  146.             ivideo.currow = DATA_TOP ;
  147.             display_ref_file() ;
  148.             break;
  149.  
  150.          case Key_END:
  151.             //  seek end of file
  152.             fseek(index, 0L, SEEK_END) ;
  153.             fgetpos(index, &pos) ;
  154.             pos -= REV_SIZE ;
  155.  
  156.             //  adjust input-file position
  157.             fsetpos(index, &pos) ;
  158.             ref.hdptr[0] = pos ;
  159.  
  160.             //  now read one line and re-position file pointer to full line
  161.             count = seek_next_line(index) ;
  162.             if (count < 0) 
  163.                error_exit(BAD_SEARCH, NULL) ;
  164.             pos += count ;
  165.             fill_ref_buffers(pos) ;
  166.  
  167.             //  now, figure out which line is top of (end of screen)
  168.             if (ref.lines[1] < window_rows) 
  169.                {
  170.                ref.cur_bfr = 0 ;
  171.                ref.offset =  ref.lines[0] + ref.lines[1] - window_rows ;
  172.                }
  173.             else 
  174.                {
  175.                ref.cur_bfr = 1 ;
  176.                ref.offset = ref.lines[1] - window_rows ;
  177.                }
  178.  
  179.             ivideo.currow = DATA_TOP ;
  180.             display_ref_file() ;
  181.             break;
  182.  
  183.          case Key_PGUP:
  184.             rtemp = ivideo.currow ;
  185.             ivideo.currow = DATA_TOP ;
  186.             for (j=0; j<window_rows; j++) 
  187.                scroll_page_down() ;
  188.             ivideo.currow = rtemp ;
  189.             break;
  190.  
  191.          case Key_DOWN:
  192.             scroll_page_up() ;
  193.             break;
  194.  
  195.          case Key_PGDN:
  196.             rtemp = ivideo.currow ;
  197.             ivideo.currow = screen_rows - 1 ;
  198.             for (j=0; j<window_rows; j++) 
  199.                scroll_page_up() ;
  200.             ivideo.currow = rtemp ;
  201.             break;
  202.  
  203.          case Key_F1:
  204.          case Key_h:
  205.          case Key_H: //  display help screen
  206.             display_help() ;
  207.             display_logo() ;
  208.             display_ref_file() ;
  209.             break;
  210.  
  211.          case Key_F2:
  212.          case Key_s:
  213.          case Key_S: //  search for string
  214.             if (message_read("Enter string to search for: ", srchstr) == 0)
  215.                {
  216.                if (search_ref_buffers(srchstr) != 0) 
  217.                    search_ref_file(srchstr) ;
  218.                }
  219.             break;
  220.  
  221.          case Key_F3:
  222.          case Key_r:
  223.          case Key_R: //  repeat last string search
  224.             if (strlen(srchstr) == 0) 
  225.                message_show("There is no current search string") ;
  226.             else if (search_ref_buffers(srchstr) != 0) 
  227.                 search_ref_file(srchstr) ;
  228.             break;
  229.  
  230.          case Key_F4:
  231.          case Key_t:
  232.          case Key_T: //  save current topic
  233.             char sfile[81] ;  //  local storage for filename
  234.             if (message_read("Enter filename to save to: ", sfile) == 0  &&
  235.                 strlen(sfile) > 0)
  236.                {
  237.                rtemp = ivideo.currow ;
  238.                process_list_file(1, sfile) ;
  239.                ivideo.currow = rtemp ;
  240.                display_ref_file() ;
  241.                }
  242.             break;
  243.  
  244.          case Key_ESC:
  245.             //  delete buffers explicitly, so the allocations
  246.             //  aren't shown by memory checkers.
  247.             delete readptr ;
  248.             delete ref.bfr[0] ;
  249.             delete ref.bfr[1] ;
  250.             delete search.bfr ;
  251.             delete list.bfr[0] ;
  252.             delete list.bfr[1] ;
  253.             done = 1 ;
  254.             break;
  255.  
  256.          default:
  257.             break;
  258.          }
  259.       }
  260.  
  261.    clear_display(char_attr) ;
  262.    home_cursor() ;
  263.    puts(THANKS_MESSAGE) ;
  264.    puts("        Copyright (c) 1995 Dan Miller") ;
  265.    puts("             derelict@netcom.com") ;
  266.    return 0;
  267.    }
  268.  
  269. //*****************************************************************
  270. //  read <UNDERSHOOT> bytes from (infile) into global (rdtemp),    
  271. //  then scan to beginning of next line and return number          
  272. //  of bytes to that next line.                                    
  273. //*****************************************************************
  274. int seek_next_line(FILE* infile)
  275.    {
  276.    int count = 0 ;
  277.    fread(rdtemp, 1, UNDERSHOOT, infile) ;
  278.    int done = 0 ;
  279.    while (!done) 
  280.       {
  281.       if (rdtemp[count] == 0x0D  ||  rdtemp[count] == 0x0A) 
  282.          {
  283.          done = 1 ;
  284.          while (rdtemp[count] == 0x0D  ||  rdtemp[count] == 0x0A) 
  285.             {
  286.             if (++count == UNDERSHOOT)
  287.                return -1 ;
  288.             }
  289.          }
  290.       else if (++count == UNDERSHOOT)
  291.          return -1 ;
  292.       }
  293.    return count;
  294.    }
  295.  
  296. //*****************************************************************
  297. ulong make_laddr(char* instr)
  298.    {
  299.    ulong ts = ((ulong) FP_SEG(instr)) << 4 ; //lint !e740
  300.    ulong to =  (ulong) FP_OFF(instr) ; //lint !e740
  301.    return ts + to ;
  302.    }
  303.  
  304. //*****************************************************************
  305. //  NULL-terminates all lines in inbfr, by converting all          
  306. //  CR and LF into NULL.  Also counts the lines and returns count. 
  307. //*****************************************************************
  308. unsigned convert_lines(char* inbfr, unsigned rcount)
  309.    {
  310.    unsigned count = 0 ;    //  output line count
  311.    unsigned bcount = 0 ;   //  input character count
  312.    while (bcount < rcount) 
  313.       {
  314.       if (*inbfr == 0x0D  ||  *inbfr == 0x0A) 
  315.          {
  316.          count++ ;
  317.          while (*inbfr == 0x0D  ||  *inbfr == 0x0A) 
  318.             {
  319.             *inbfr++ = 0 ;
  320.             bcount++ ;
  321.             }
  322.          }
  323.       else 
  324.          {
  325.          inbfr++ ;
  326.          bcount++ ;
  327.          }
  328.       }
  329.    return count ;
  330.    }
  331.  
  332. //*****************************************************************
  333. //  parse lines from input file.
  334. //  Back file up to 
  335. //*****************************************************************
  336. unsigned fill_search_buffer(FILE* infile)
  337.    {
  338.    int done = 0 ;
  339.    //lint -e740
  340.    unsigned offseti = FP_OFF(readptr) ;   // init value for byte tfr counter
  341.    unsigned offsetf ;
  342.    unsigned count = 0, j ;
  343.  
  344.    //  fill the readbfr from ref file
  345.    unsigned rlines = fill_read_buffer(infile) ;
  346.    if (rlines == 0) 
  347.       return 0;
  348.  
  349.    //  DEBUG:
  350.    ulong iaddr = make_laddr(search.bfr[0].instr) ;
  351.  
  352.    //  now, translate the read buffer into the ref-list buffer
  353.    unsigned lcount = isl_lines ;
  354.    char *sptr = readptr ;
  355.    while (!done) 
  356.       {
  357.       unsigned slen = strlen(sptr) ;
  358.  
  359.       //  DEBUG:
  360.       {
  361.       ulong saddr = make_laddr(search.bfr[count].instr) ;
  362.       if ((saddr+slen - iaddr) > (ulong) BFR_SIZE) 
  363.          {
  364.          printf("\nSearch overrun:\n") ;
  365.          printf("count = %d\n", count) ;
  366.          printf("iaddr=%ld, saddr=%ld\n", iaddr, saddr) ;
  367.          exit(1) ;
  368.          }
  369.       }
  370.       strcpy(search.bfr[count].instr, sptr) ;
  371.  
  372.       //  pad short lines with spaces
  373.       if (slen < sizeof(sum_conv)) 
  374.          {
  375.          for (j=slen; j<last_ref_char; j++) 
  376.             search.bfr[count].instr[j] = ' ' ;
  377.          //  now, NULL-terminate the line
  378.          search.bfr[count].instr[last_ref_char] = 0 ;
  379.          }
  380.  
  381.       //  point to next string in buffer
  382.       sptr += slen ;
  383.       while (*sptr == 0)  sptr++ ;  //  skip NULLs at end of last line
  384.  
  385.       count++ ;
  386.       //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  387.       //  If this terminates on lcount, rather than rlines, 
  388.       //  the input buffer will have to be adjusted
  389.       //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  390.       if (--lcount == 0  ||  count == rlines) 
  391.          {
  392.          done = 1 ;
  393.          //  set tail-pointer variable in current ref struct
  394.          offsetf = FP_OFF(sptr) ;   //lint !e740
  395.          search.tlptr = search.hdptr + (offsetf - offseti) ;
  396.          fsetpos(infile, &search.tlptr) ; //  adjust input-file position
  397.          }
  398.       }
  399.  
  400.    return count;
  401.    }
  402.  
  403. //*****************************************************************
  404. //  Read a buffer-worth of raw data into readbfr,
  405. //  do a partial read-and-fill to ensure that it contains
  406. //  a full line at the end,
  407. //  then replace all 0x0D and 0x0A with NULLs.
  408. //  Return a count of lines.
  409. //  
  410. //  This routine reads from the current input file pointer
  411. //*****************************************************************
  412. unsigned fill_read_buffer(FILE* infile)
  413.    {
  414.    //***********************************************************
  415.    //  read data into read buffer and ensure even-line boundary.
  416.    //  This method assumes that the input file has already      
  417.    //  been correctly positioned using fseek().                 
  418.    //***********************************************************
  419.    unsigned rbytes = fread(readptr, 1, ((unsigned) BFR_SIZE)-UNDERSHOOT, infile) ;
  420.    if (rbytes == 0) 
  421.       return 0;
  422.  
  423.    //***********************************************************
  424.    //                   FILL LAST LINE                          
  425.    //  if last line doesn't already end with a newline,         
  426.    //  read more data to get there, and tack it on the end.     
  427.    //***********************************************************
  428.    char* endptr = readptr + rbytes - 1 ;
  429.    if (*endptr != 0x0D  &&  *endptr != 0x0A)
  430.       {
  431.       unsigned slen = fread(rdtemp, 1, UNDERSHOOT, infile) ;
  432.       if (slen == 0) 
  433.          error_exit(NO_READ_FILE, "reading infile") ;
  434.  
  435.       unsigned j=0; 
  436.       //  search for newline (it MUST be there!!)
  437.       while (rdtemp[j] != 0x0D  &&  rdtemp[j] != 0x0A)
  438.          {
  439.          j++ ;
  440.          if (j >= UNDERSHOOT) 
  441.             error_exit(BAD_FORMAT, rdtemp) ;
  442.          }
  443.       //  then NULL-out and count the newlines
  444.       while (rdtemp[j] == 0x0D  ||  rdtemp[j] == 0x0A)
  445.          {
  446.          rdtemp[j] = 0 ;
  447.          j++ ;
  448.          if (j >= UNDERSHOOT) 
  449.             error_exit(BAD_FORMAT, rdtemp) ;
  450.          }
  451.       slen = j ;
  452.  
  453.       //  copy the extra bytes into read buffer
  454.       for (j=0; j<slen; j++) 
  455.          {
  456.          *endptr++ = rdtemp[j] ;
  457.          }
  458.       rbytes += slen ;
  459.       }
  460.  
  461.    //  NULL-terminate and count the lines in read buffer.
  462.    return convert_lines(readptr, rbytes) ;
  463.    }
  464.  
  465. //*****************************************************************
  466. void display_logo(void)
  467.    {
  468.    dprints(0, 0, LOGO, logo) ;
  469.    dprints(0, 1, LOGO, dividers) ;
  470.    dprints(0, 2, LOGO, header) ;
  471.    dprints(0, 3, LOGO, dividerd) ;
  472.    }
  473.  
  474. //*****************************************************************
  475. //  Build the indexed reference list
  476. //*****************************************************************
  477. void build_index(void)
  478.    {
  479.    union sum_conv outList ; 
  480.    char lname[_MAX_PATH] ;
  481.    FILE* idxfile ;
  482.    FILE* infile ;
  483.    fpos_t fpos ;
  484.    char instr[128], outstr[80] ;
  485.    unsigned lflag ;
  486.    char lext, extn[3] = ".x" ;
  487.    unsigned long out_lines = 0L ;
  488.  
  489.    _makepath(tempstr, ildrive, ilpath, "interrup", "idx") ;
  490.    idxfile = fopen(tempstr, "wb") ;
  491.    if (idxfile == NULL) 
  492.       error_exit(NO_WRITE_FILE, "INTERRUP.IDX") ;
  493.  
  494.    puts(Version) ;
  495.    puts("Building index file... this will take a couple of minutes") ;
  496.  
  497.    _makepath(lname, ildrive, ilpath, "interrup", "lst") ;
  498.    infile = fopen(lname, "rb") ;
  499.    if (infile == NULL) //  then combined file does not exist; use parts
  500.       {
  501.       lflag = 0 ;
  502.       lext = 'a' ;
  503.       printf("reading INTERRUP.x sections: ") ;
  504.       _makepath(lname, ildrive, ilpath, "interrup", "a") ;
  505.       infile = fopen(lname, "rb") ;
  506.       if (infile == NULL) 
  507.          {
  508.          fclose(idxfile) ;
  509.          unlink(tempstr) ;
  510.          error_exit(NO_LIST_FILE, lname) ;
  511.          }
  512.       }
  513.    else 
  514.       {
  515.       lflag = 1 ;
  516.       lext = ' ' ;
  517.       printf("reading INTERRUP.LST: ") ;
  518.       }
  519.    fclose(infile) ;
  520.  
  521.    int done = 0 ;
  522.    while (!done) 
  523.       {
  524.       //  open the next input file
  525.       infile = fopen(lname, "rb") ;
  526.       //  if next file can't be opened, we're done!!
  527.       if (infile == NULL) 
  528.          {
  529.          fclose(idxfile) ;
  530.          printf("\nRef file contains %lu lines\n", out_lines) ;
  531.          return ;
  532.          }
  533.       putchar(lext) ;
  534.  
  535.       fpos = 0L ;
  536.       //  now that the next List file is open, 
  537.       //  start searching for divider lines
  538.       while ((fgets(instr, 128, infile)) != NULL)
  539.          {
  540.          if (strncmp(instr, "--------", 8) == 0  &&  
  541.              instr[9] == '-'  &&
  542.              instr[8] != '!'
  543.             ) 
  544.             {
  545.             out_lines++ ;
  546.  
  547.             //  reset the output data field
  548.             memset(outList.idx.data, ' ', 80) ;
  549.  
  550.             outstr[ 0] = ' ' ;
  551.             outstr[ 1] = instr[10] ; //  INT number
  552.             outstr[ 2] = instr[11] ;
  553.             outstr[ 3] = ' ' ;
  554.             outstr[ 4] = instr[12] ; //  AH contents
  555.             outstr[ 5] = instr[13] ;
  556.             outstr[ 6] = ' ' ;
  557.             outstr[ 7] = instr[14] ; //  AL contents
  558.             outstr[ 8] = instr[15] ;
  559.             outstr[ 9] = ' ' ;
  560.             outstr[10] = instr[8] ; //  classification
  561.             outstr[11] = '>' ;
  562.  
  563.             outList.idx.file = lext ;
  564.             sprintf(outList.idx.foffset, "%08lX", fpos) ;
  565.             outList.idx.null_term = ' ' ; //  replace NULL with SPACE in file
  566.  
  567.             //  move instr up to description line
  568.             fgets(instr, 128, infile) ;
  569.  
  570.             //  Trim line to 80 chars
  571.             int inlen = strlen(instr) ;
  572.             while (instr[inlen-1] == 0x0D  ||  instr[inlen-1] == 0x0A) 
  573.                {
  574.                instr[--inlen] = 0 ;
  575.                }
  576.  
  577.             strncpy(&outstr[12], &instr[8], 80-13) ;  //  append to outstr
  578.             outstr[80] = 0 ;  //  add safety NULL-terminator
  579.             strcpy(outList.idx.data, outstr) ;
  580.             fprintf(idxfile, "%s\r\n", outList.instr) ;
  581.             }  //  if line matches search pattern, add to index file
  582.  
  583.          fgetpos(infile, &fpos) ; //  update input-file pointer
  584.          }  //  if input file not yet empty
  585.       fclose(infile) ;
  586.       if (lext == ' ') 
  587.          {
  588.          done = 1 ;
  589.          fclose(idxfile) ;
  590.          }
  591.       else 
  592.          {
  593.          extn[1] = ++lext ;
  594.          _makepath(lname, ildrive, ilpath, "interrup", extn) ;
  595.          }
  596.       }  //  while not done parsing files
  597.    }
  598.  
  599.